From 80d4a08e306e36486e45542af0cdc58f5ad21e45 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 8 Dec 2020 21:33:06 +0100 Subject: [PATCH] gdk/surface: Delay gdk_surface_request_motion() requests internally Those requests are received while dealing with the ::layout frame clock phase, this has the unintended side effect of making the frame clock "rewind" to handle ::flush-events again during this frame, which delays everything and practically halves the frame rate. We do intend to make the motion events dispatches on the next frame, so do this in an idle at a slightly lower priority than layout/draw, so the ::flush-events phase is actually requested for the next frame. Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3264 --- gdk/gdksurface.c | 28 ++++++++++++++++++++++------ gdk/gdksurfaceprivate.h | 2 ++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index 012864479a..b6f739c5c0 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -681,6 +681,8 @@ gdk_surface_finalize (GObject *object) { GdkSurface *surface = GDK_SURFACE (object); + g_clear_handle_id (&surface->request_motion_id, g_source_remove); + g_signal_handlers_disconnect_by_func (surface->display, seat_removed_cb, surface); @@ -2408,6 +2410,19 @@ gdk_surface_flush_events (GdkFrameClock *clock, surface->frame_clock_events_paused = TRUE; } +static gboolean +request_motion_cb (void *data) +{ + GdkSurface *surface = GDK_SURFACE (data); + GdkFrameClock *clock = gdk_surface_get_frame_clock (surface); + + if (clock) + gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS); + surface->request_motion_id = 0; + + return G_SOURCE_REMOVE; +} + static void gdk_surface_resume_events (GdkFrameClock *clock, void *data) @@ -2419,6 +2434,13 @@ gdk_surface_resume_events (GdkFrameClock *clock, _gdk_display_unpause_events (surface->display); surface->frame_clock_events_paused = FALSE; } + + if (surface->request_motion) + { + surface->request_motion_id = + g_idle_add_full (GDK_PRIORITY_REDRAW + 1, + request_motion_cb, surface, NULL); + } } static void @@ -2912,13 +2934,7 @@ gdk_surface_handle_event (GdkEvent *event) void gdk_surface_request_motion (GdkSurface *surface) { - GdkFrameClock *frame_clock; - surface->request_motion = TRUE; - - frame_clock = gdk_surface_get_frame_clock (surface); - if (frame_clock) - gdk_frame_clock_request_phase (frame_clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS); } /** diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h index 27a3966fe7..2126371853 100644 --- a/gdk/gdksurfaceprivate.h +++ b/gdk/gdksurfaceprivate.h @@ -80,6 +80,8 @@ struct _GdkSurface guint shortcuts_inhibited : 1; guint request_motion : 1; + guint request_motion_id; + struct { GdkGravity surface_anchor; GdkGravity rect_anchor; -- 2.30.2